#ifndef __LIB_TAHSM_SJJ1507_H__
#define __LIB_TAHSM_SJJ1507_H__

#ifdef _WIN32
#define TAAPI _declspec (dllexport)
#else
#define TAAPI
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifndef SGD_SM4_ECB
    #define SGD_SM4_ECB	     0x00000401	// SM4算法ECB加密模式
#endif
#ifndef SGD_SM4_CBC
    #define SGD_SM4_CBC	     0x00000402	// SM4算法CBC加密模式
#endif
#ifndef SGD_SM4_CFB
    #define SGD_SM4_CFB	     0x00000404	// SM4算法CFB加密模式
#endif
#ifndef SGD_SM4_OFB
    #define SGD_SM4_OFB	     0x00000408	// SM4算法OFB加密模式
#endif
    /**
     * @brief   初始化接口
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_Initialize(void);

    /**
     * @brief   释放接口资源
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_Finallize(void);

    /**
     * @brief   生成指定长度的随机数据
     *
     * @param   uiLength        [in]    指定生成随机数的字节数
     * @param   pucRandom       [out]   生成的随机数
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_GenerateRandom(unsigned int uiLength, unsigned char *pucRandom);

    /**
     * @brief   公钥验签名操作（用于验证前端上送的签名值）
     *
     * @param   pucPublicKey[64]    [in]    用于验签名的前端设备或终端设备的公钥数据
     * @param   pucData             [in]    签名数据原文
     * @param   uiDataLength        [in]    签名数据原文的字节数
     * @param   pucSignature[64]    [in]    签名值
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_SM2Verify(
        unsigned char pucPublicKey[64],
        unsigned char *pucData, unsigned int  uiDataLength,
        unsigned char pucSignature[64]);

    /**
     * @brief   调用密码机设备中指定索引下的SM2私钥进行签名运算
     *  
     * @param   uiKeyIndex          [in]    签名私钥索引值
     * @param   pucData             [in]    签名数据原文
     * @param   uiDataLength        [in]    签名数据原文的字节数
     * @param   pucSignature[64]    [out]   输出签名值结果  
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_SM2Sign(
        unsigned int uiKeyIndex,
        unsigned char *pucData, unsigned int uiDataLength,
        unsigned char pucSignature[64]);

    /**
     * @brief   密码机根据平台主密钥和设备ID版本号信息生成前端设备的VKEK密钥
     *
     * @param   uiPMKIndex                  [in]    平台主密钥索引号
     * @param   uiLKIndex                   [in]    本地保护密钥索引号
     * @param   pucPublicKey[64]            [in]    前端设备公钥数据
     * @param   pucDeviceID                 [in]    前端设备ID
     * @param   uiIDlen                     [in]    前端设备ID字节长度
     * @param   pucVersion                  [in]    VKEK版本号（建议使用精确到秒的19位格式化时间字符串）
     * @param   uiVersionLen                [in]    VKEK版本号长度
     * @param   pucCipherByLK[16]           [out]   输出本地保护密钥加密的VKEK密文（用于存储在服务端数据库中）
     * @param   pucCipherByPK[112]          [out]   输出前端设备公钥加密的VKEK密文（用于返回给前端设备使用）
     * @param   pucCV[8]                    [out]   输出VKEK的密钥校验数据（于pucCipherByLK一起存储于数据库中，可用于验证密钥正确性）
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_GenerateVKEK(
        unsigned int uiPMKIndex,
        unsigned int uiLKIndex,
        unsigned char pucPublicKey[64],
        unsigned char *pucDeviceID, unsigned int uiIDlen,
        unsigned char *pucVersion, unsigned int uiVersionLen,
        unsigned char pucCipherByLK[16],
        unsigned char pucCipherByPK[112],
        unsigned char pucCV[8]);

    /**
     * @brief   本地保护密钥加密的VKEK转为指定公钥加密
     *
     * @param   uiLKIndex                   [in]    本地保护密钥的索引号
     * @param   pucCipherByLK[16]           [in]    本地保护密钥加密的VKEK密文数据
     * @param   pucPublicKey[64]            [in]    公钥数据（使用的公钥应为数据库中存储的有效的前端或终端设备的公钥值）
     * @param   pucCV[8]                    [in]    VKEK的密钥校验数据
     * @param   pucCipherByPK[112]          [out]   输出公钥加密的VKEK数据
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_TransVKEK(
        unsigned int uiLKIndex,
        unsigned char pucCipherByLK[16],
        unsigned char pucPublicKey[64],
        unsigned char pucCV[8],
        unsigned char pucCipherByPK[112]);

    /**
     * @brief   对称算法加密数据
     *
     * @param   uiLKIndex               [in]    指定本地保护密钥的索引号（用于恢复VKEK）
     * @param   pucVKEKCipherByLK[16]   [in]    本地保护密钥加密的VKEK密文（用于恢复VEK）
     * @param   pucVEKCipherByVKEK[16]  [in]    VKEK加密的VEK密文数据（用于加密数据）
     * @param   uiAlgID                 [in]    指定加密使用算法标识（推荐使用 SGD_SM4_OFB）
     * @param   pucIv                   [in]    加密数据时使用的初始向量值
     * @param   pucData                 [in]    待加密的数据
     * @param   uiDataLen               [in]    待加密的数据字节长度
     * @param   pucEncData              [out]   输出加密后的密文数据   
     * @param   puiEncDataLen           [out]   输出密文数据的字节长度
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_SymmEncrypt(
        unsigned int uiLKIndex,
        unsigned char pucVKEKCipherByLK[16],
        unsigned char pucVEKCipherByVKEK[16],
        unsigned int uiAlgID,
        unsigned char *pucIv,
        unsigned char *pucData, int uiDataLen,
        unsigned char *pucEncData, int *puiEncDataLen);

    /**
     * @brief   对称算法解密数据
     *
     * @param   uiLKIndex               [in]    指定本地保护密钥的索引号（用于恢复VKEK）
     * @param   pucVKEKCipherByLK[16]   [in]    本地保护密钥加密的VKEK密文（用于恢复VEK）
     * @param   pucVEKCipherByVKEK[16]  [in]    VKEK加密的VEK密文数据（用于加密数据）
     * @param   uiAlgID                 [in]    指定加密使用算法标识（推荐使用 SGD_SM4_OFB）
     * @param   pucIv                   [in]    加密数据时使用的初始向量值
     * @param   pucData                 [in]    待解密的数据
     * @param   uiDataLen               [in]    待解密的数据字节长度
     * @param   pucEncData              [out]   输出解密后的明文数据   
     * @param   puiEncDataLen           [out]   输出明文数据的字节长度
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_SymmDecrypt(
        unsigned int uiLKIndex,
        unsigned char pucVKEKCipherByLK[16],
        unsigned char pucVEKCipherByVKEK[16],
        unsigned int uiAlgID,
        unsigned char *pucIv,
        unsigned char *pucEncData, int uiEncDataLen,
        unsigned char *pucData, int *puiDataLen);

    TAAPI int TA_Hash_SM3(unsigned char * pucData, int nDataLen, unsigned char pucHash[32]);


    /**
     * @brief   获取指定索引下的SM2公钥数据
     *
     * @param   uiIndex         [in]    指定获取公钥的索引号
     * @param   pucPubkey[64]   [out]   输出公钥数据
     *
     * @return  成功返回0，否则返回相应错误代码
     */
    TAAPI int TA_GetPublicKey(unsigned int uiIndex, unsigned char pucPubkey[64]);

#ifdef __cplusplus
}
#endif

#ifndef __ERRORCODE_TALIB__
/*
 * 接口错误代码定义
 *  此处定义错误代码仅为接口在本地处理逻辑中发生错误时报出
 *  如得到其他错误代码则为调用密码机底层接口是返回，需查阅SDF接口错误代码定义
 */
#define TALIBR_OK               0x0         // 未发生错误（功能执行成功）
#define TALIBR_INIT             0x0100      // 函数初始化失败，或未初始化
#define TALIBR_FINAL            0x0200      // 函数初始化失败，或未初始化
#define TALIBR_PARAMETER        0x0300      // 函数传递参数错误
#define TALIBR_MEMORY           0x0400      // 内存操作失败（一般是内存分配失败）

#endif //__ERRORCODE_TAHSM__

#endif //__LIB_TAHSM_SJJ1507_H__
